﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WoWConnecter.Chat;

namespace WoWConnecter.Entities
{
    public partial class UserCharacter
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        public void SendChannelListRequest(string channel)
        {
            RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.CMSG_CHANNEL_LIST);
            packet.WriteCString(channel);
            Send(packet);
        }

        /// <summary>
        /// Sends the request to join a channel
        /// </summary>
        /// <param name="channel">Target Channel</param>
        /// <param name="channelType">Type of channel</param>
        /// <param name="password">Password of channel</param>
        public void SendChannelJoin(string channel, uint channelType = 0x4, string password = "")
        {
            RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.CMSG_JOIN_CHANNEL);
            
            packet.Write(channelType);

            packet.WriteByte(0); //Unk
            packet.WriteByte(0); //Unk

            packet.WriteCString(channel);
            packet.WriteCString(password);
            Send(packet);
        }

        /// <summary>
        /// Sends a message to a channel
        /// </summary>
        /// <param name="message">Message to send</param>
        /// <param name="channel">Target Channel</param>
        /// <param name="language">Language of message</param>
        public void SendChannelMessage(string message, Channel channel, ChatLanguage language)
        {
            RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.CMSG_MESSAGECHAT);
            packet.Write((uint)ChatMsgType.Channel);
            packet.Write((uint)language);
            packet.WriteCString(channel.Name);
            packet.WriteCString(message);
            Send(packet);
        }

        /// <summary>
        /// Requests a characters name, race, class, and gender
        /// </summary>
        /// <param name="id"></param>
        public void SendCharacterInfoRequest(EntityId id)
        {
            RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.CMSG_NAME_QUERY);
            packet.Write(id);
            Send(packet);
        }

        [PacketMethod(RealmServerOpCode.SMSG_NAME_QUERY_RESPONSE)]
        private void HandleCharacterInfoRequest(RealmPacketIn packet)
        {
            Character character = new Character(packet);

            if (!mKnownCharacters.ContainsKey(character.Id))
                mKnownCharacters.Add(character.Id, character);

            if (mPendingCharacterRequests.ContainsKey(character.Id))
            {
                foreach (Action<Character> action in mPendingCharacterRequests[character.Id])
                {
                    action(character);
                }

                mPendingCharacterRequests[character.Id].Clear();
                mPendingCharacterRequests.Remove(character.Id);
            }
        }


        [PacketMethod(RealmServerOpCode.CMSG_CHANNEL_LIST)]
        private void HandleChannelList(RealmPacketIn packet)
        {
            packet.ReadByte(); //Unknown
            string channelName = packet.ReadCString();
            ChatChannelFlags flags = (ChatChannelFlags)packet.ReadByte();
            uint userCount = packet.ReadUInt32();

        }

        [PacketMethod(RealmServerOpCode.SMSG_CHANNEL_NOTIFY)]
        private void HandleChannelNotify(RealmPacketIn packet)
        {
            byte result = packet.ReadByte();
            Channel channel = null;

            switch (result)
            {
                case 2: //Success
                    {
                        channel = new Channel(this, packet.ReadCString(), packet.ReadByte(), packet.ReadUInt32());
                        mChannels.Add(channel.Name, channel);
                        SendChannelListRequest(channel.Name);
                    } break;
                default: break;
            }

            if (JoinChannelResult != null)
                JoinChannelResult(result, channel);
        }

        [PacketMethod(RealmServerOpCode.SMSG_MESSAGECHAT)]
        private void HandleChannelMessage(RealmPacketIn packet)
        {
            ChatMsgType type = (ChatMsgType)packet.ReadByte();
            ChatLanguage language = (ChatLanguage)packet.ReadUInt32();

            switch (type)
            {
                case ChatMsgType.Channel:
                    {
                        EntityId notsure = packet.ReadEntityId();
                        packet.ReadInt32(); //Unknown
                        string name = packet.ReadCString();
                        EntityId sender = packet.ReadEntityId(); //Second one?

                        //TODO: Create a packet method to do this
                        int msgLenght = packet.ReadInt32();
                        string message = ASCIIEncoding.ASCII.GetString(packet.ReadBytes(msgLenght));

                        //Remove null termination
                        message = message.Remove(message.Length - 1);

                        ChatTag chatTag = (ChatTag)packet.ReadByte();
                        Channel channel = GetChannel(name);

                        if (channel != null)
                        {
                            ChatMessage msg;

                            Action<Character> action = delegate(Character chr) {
                                msg = new ChatMessage(channel, chr, language, (ChatTag)chatTag, message);
                                
                            };

                            Character character = GetCharacter(sender, action);

                            if (character != null)
                                action(character);
                        }
                    } break;
            }
        }
    }
}